﻿package net.wangit.view.tree;

import java.util.List;

import net.wangit.User;
import net.wangit.context.ActionContext;
import net.wangit.context.LocalContext;
import net.wangit.framework.expression.LabelExpression;
import net.wangit.support.TreeWriter;
import net.wangit.user.Developer;
import net.wangit.util.Checker;
import net.wangit.view.tree.config.TreeActionType;
import net.wangit.view.tree.config.TreeType;
import net.wangit.view.unit.UnitComponent;
import net.wangit.view.unit.UnitFactory;
import net.wangit.view.util.Html;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;


public class DefaultTreeWriter implements TreeWriter {

	private static final Log log = LogFactory
			.getLog(net.wangit.view.tree.DefaultTreeWriter.class);
	private static final String GLOBAL_PREFIX = "_ft_";
	private String prefix;

	public DefaultTreeWriter() {
	}

	public String write(Tree tree) {
		TreeConfig config = tree.getConfig();
		prefix = (new StringBuilder(DefaultTreeWriter.GLOBAL_PREFIX)).append(
				config.getTreeId()).toString();
		boolean filter = config.isFilter();
		ActionContext ac = null;
		User user = null;
		if (filter) {
			ac = LocalContext.getLocalContext().getActionContext();
			user = ac.getVisitor().getUser();
		}
		StringBuffer html = new StringBuffer("<div");
		Html.setVisible(html, config.isVisible());
		html.append(" oncontextmenu=\"return false\">");
		html.append("<script>");
		setSettings(html, config);
		write(tree, html, "", true, filter, ac, user);
		switch (config.getType()) {
		case TreeType.TREE:
			html.append(getVarName(tree)).append(".writeTree();");
			break;

		case TreeType.MENU:
			html.append(getVarName(tree)).append(".writeBar();");
			break;
		}
		html.append("</script></div>");
		return html.toString();
	}

	private void setSettings(StringBuffer html, TreeConfig config) {
		String imagesPath = config.getImagePath();
		if (!Checker.isEmpty(imagesPath))
			html.append("TreeSettings.imagesPath = \"").append(imagesPath)
					.append("\";");
		String divAttribute = config.getDivAttribute();
		if (!Checker.isEmpty(divAttribute))
			html.append("TreeSettings.containerAttribute = \"").append(
					divAttribute).append("\";");
		String defaultTarget = config.getDefaultTarget();
		if (!Checker.isEmpty(defaultTarget))
			html.append("TreeSettings.defaultTarget = \"")
					.append(defaultTarget).append("\";");
		if (config.isDefaultOpen())
			html.append("TreeSettings.defaultOpen = true;");
		if (!config.isShowLines())
			html.append("TreeSettings.showLines = false;");
		if (!config.isShowIcons())
			html.append("TreeSettings.showIcons = false;");
		if (config.isSupportCheck())
			html.append("TreeSettings.supportCheck = true;");
		if (config.isSupportCheckAll())
			html.append("TreeSettings.supportCheckAll = true;");
		if (config.isSupportMove())
			html.append("TreeSettings.moveable = true;");
		if (config.isSupportAdd())
			html.append("TreeSettings.addible = true;");
		if (!Checker.isEmpty(config.getMoveBeforeInterceptor()))
			html.append("TreeSettings.moveBeforeInterceptor = \"").append(
					config.getMoveBeforeInterceptor()).append("\";");
		if (!Checker.isEmpty(config.getMoveAfterInterceptor()))
			html.append("TreeSettings.moveAfterInterceptor = \"").append(
					config.getMoveAfterInterceptor()).append("\";");
	}

	private boolean write(Tree tree, StringBuffer html,
			String parentOjbectName, boolean enabled, boolean filter,
			ActionContext ac, User user) {
		write(ac, tree, html, enabled);
		boolean hasLeafs = false;
		List<Tree> leafs = tree.getLeafs();
		if (leafs != null) {
			String objectName = getVarName(tree);
			for (int i = 0; i < leafs.size(); i++) {
				Tree leaf = leafs.get(i);
				if (filter && !hasPrivilege(leaf, ac, user)) {
					if (leaf.getFilterMode() == 1)
						hasLeafs = write(leaf, html, objectName, false, filter,
								ac, user);
				} else {
					hasLeafs = write(leaf, html, objectName, true, filter, ac,
							user);
				}
			}

		}
		if (!parentOjbectName.equals("")
				&& (!filter || leafs == null || hasLeafs || !Checker
						.isEmpty(tree.getAction()))) {
			html.append(parentOjbectName).append(".add(").append(
					getVarName(tree)).append(");");
			return true;
		} else {
			return false;
		}
	}

	private void write(ActionContext ac, Tree tree, StringBuffer html,
			boolean enabled) {
		String objectName = getVarName(tree);
		String name = LabelExpression.resolve(ac, tree.getName());
		html.append("var ").append(objectName).append(" = new Tree(\"").append(
				tree.getId()).append("\",\"").append(name).append("\",")
				.append(getAction(tree, enabled)).append(",\"");
		if (!Checker.isEmpty(tree.getIcon()))
			html.append(tree.getIcon());
		html.append("\",\"");
		if (!Checker.isEmpty(tree.getAttribute()))
			html.append(tree.getAttribute());
		html.append("\"); ");
		if (!Checker.isEmpty(tree.getTarget()))
			html.append(objectName).append(".target=\"").append(
					tree.getTarget()).append("\";");
		if (!Checker.isEmpty(tree.getCss()))
			html.append(objectName).append(".css=\"").append(tree.getCss())
					.append("\";");
		String title = tree.getTitle();
		if (!Checker.isEmpty(title)) {
			title = LabelExpression.resolve(ac, title);
			html.append(objectName).append(".title=\"").append(title).append(
					"\";");
		}
		if (!Checker.isEmpty(tree.getOpenIcon()))
			html.append(objectName).append(".openIcon=\"").append(
					tree.getOpenIcon()).append("\";");
		if (!Checker.isEmpty(tree.getCheckValue()))
			html.append(objectName).append(".checkValue=\"").append(
					tree.getCheckValue()).append("\";");
		if (!Checker.isEmpty(tree.getCheckAttribute()))
			html.append(objectName).append(".checkAttribute=\"").append(
					tree.getCheckAttribute()).append("\";");
	}

	private String getVarName(Tree tree) {
		String id = (new StringBuilder(String.valueOf(prefix))).append(
				tree.getId()).toString();
		id = id.replace('.', '_');
		id = id.replace('-', '_');
		return id;
	}

	private String getAction(Tree tree, boolean enabled) {
		String action = tree.getAction();
		if (!enabled || Checker.isEmpty(action))
			return "null";
		if (tree.getActionType() == TreeActionType.LINK)
			return (new StringBuilder("\"")).append(action).append("\"")
					.toString();
		else
			return action;
	}

	private boolean hasPrivilege(Tree tree, ActionContext ac, User user) {
		String unitId;
		String domain;
		try {
			unitId = tree.getTargetUnitId();
			if (Checker.isEmpty(unitId))
				return true;
			domain = tree.getTargetDomain();
			UnitComponent uc = UnitFactory.getUnitWithoutClone(domain, unitId);
			if (!uc.isPublished())
				return user instanceof Developer;
			if (uc.hasAccessPrivileges())
				return user.hasUnitPrivilege(domain, unitId, tree
						.getTargetUnitShowMode());
			else
				return true;
		} catch (Exception e) {
			log.error("can't create unit!", e);
			return false;
		}
	}

}
